package 多线程;

//公平锁和非公平锁的测试
//①测试目的:
//非公平锁在获取锁的时候会首先进行抢锁，在获取锁失败后才会将当前线程加入同步队列队尾中，而公平锁则是符合请求的绝对顺序，也就是会按照先来后
//到FIFO。在下面的代码中我们使用一个静态内部类继承了ReentrantLock并重写等待队列的方法，作为测试的ReentrantLock。然后创建5个线程，
//每个线程连续两次去获取锁，分别测试公平锁和非公平锁的测试结果:

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//import java.util.concurrent.locks.ReentrantLock.FairSync;
//import java.util.concurrent.locks.ReentrantLock.NonfairSync;

//import org.junit.Test;

public class TestReentrantLock {
	/**
	 * ReentrantLock的构造方法 public ReentrantLock(boolean fair) {sync = fair ? new
	 * FairSync() : new NonfairSync();}
	 */
	private Lock fairLock = new ReentrantLock2(true);
	private Lock unFairLock = new ReentrantLock2(false);

	@Test
	public void testFair() throws InterruptedException {
		System.out.println("测试公平锁:");
		testLock(fairLock); // 测试公平锁
	}

	@Test
	public void testUnFair() throws InterruptedException {
		System.out.println("测试非公平锁:");
		testLock(unFairLock); // 测试非公平锁
	}

	private void testLock(Lock lock) throws InterruptedException {
		for (int i = 0; i < 5; i++) {
			Thread thread = new Thread(new Job(lock)){
				public String toString() {
					return getName();
				}
			};
			thread.setName(i + "");
			thread.start();
		}
		TimeUnit.SECONDS.sleep(6);
		//Thread.sleep(6000);
	}

	//private static class Job extends Thread {
	private static class Job implements Runnable {
		private Lock lock;

		public Job(Lock lock) {
			this.lock = lock;
		}

		@Override
		public void run() {
			// 两次打印当前线程和等待队列中的Threads
			for (int i = 0; i < 1; i++) {
				lock.lock(); // 获取锁
				try {
					//Thread.sleep(1000);
					TimeUnit.SECONDS.sleep(1);
					System.out.println("当前线程=>" + Thread.currentThread().getName() + " " + "等待队列中的线程=>"
							+ ((ReentrantLock2) lock).getQueuedThreads());
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock(); // 释放锁
				}
			}
		}

	}

	private static class ReentrantLock2 extends ReentrantLock {
		/** 
		* @Fields serialVersionUID : TODO 
		*/
		private static final long serialVersionUID = 1L;

		public ReentrantLock2(boolean fair) {
			//public ReentrantLock(boolean fair) {
		    //    sync = fair ? new FairSync() : new NonfairSync();
		    //}
			super(fair);//调用父类构造函数
		}

		public Collection<Thread> getQueuedThreads() { // 逆序打印等待队列中的线程
			//protected Collection<Thread> getQueuedThreads() {
		    //   return sync.getQueuedThreads();
		    //}
			List<Thread> list = new ArrayList<Thread>(super.getQueuedThreads());//获取线程队列
			Collections.reverse(list);
			return list;
		}
	}

}
